package com.itheima.app.manager;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.autoconfig.oss.OssTemplate;
import com.itheima.domain.db.UserInfo;
import com.itheima.domain.mongo.Comment;
import com.itheima.domain.mongo.Movement;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.mongo.CommentService;
import com.itheima.service.mongo.MovementService;
import com.itheima.util.ConstantUtil;
import com.itheima.vo.CommentVo;
import com.itheima.vo.MovementVo;
import com.itheima.vo.PageBeanVo;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Component
public class MovementManager {

    @DubboReference
    MovementService movementService;

    @Autowired
    OssTemplate ossTemplate;

    @DubboReference
    UserInfoService userInfoService;

    @DubboReference
    CommentService commentService;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    RabbitTemplate rabbitTemplate;

    @Autowired
    MQMovementManager mqMovementManager;

    public void save(Movement movement, MultipartFile[] imageContent) throws IOException {
        //1.获取登陆者id
        Long userId = UserHolder.get().getId();

        //2.将所有图片上传到oss上,获取地址列表
        List<String> images = new ArrayList();
        if (ArrayUtil.isNotEmpty(imageContent)) {
            for (MultipartFile file : imageContent) {
                String url = ossTemplate.upload(file.getOriginalFilename(), file.getInputStream());
                images.add(url);
            }
        }

        //3.封装movement(id,userId,图片列表等)
        movement.setId(ObjectId.get());
        movement.setUserId(userId);
        //设置动态图片集合
        movement.setMedias(images);
        //TODO 等内容审核讲完之后,再将动态状态设置0
        //movement.setState(1);//已审核
        movement.setState(0);//未审核
        movement.setCreated(System.currentTimeMillis());
        movement.setSeeType(1);//本版本暂时没有实现这个功能

        //4.远程调用service完成动态发布
        movementService.save(movement);

        //5.将动态的id放入mq中
        rabbitTemplate.convertAndSend("tanhua.movement.state",movement.getId().toString());

        //6.将用户的行为得分放入mq中
        mqMovementManager.sendMovement(userId,movement.getId(),MQMovementManager.MOVEMENT_PUBLISH);
    }

    public ResponseEntity findMyMovementByPage(Long userId, Integer pageNum, Integer pageSize) {
        //0.远程调用service查询userInfo
        UserInfo userInfo = userInfoService.findById(userId);

        //1.远程调用service查询当前页的数据
        PageBeanVo pageBeanVo = movementService.findMyMovementByPage(userId, pageNum, pageSize);

        //2.获取pageBeanVo中items(动态详情)
        List<Movement> items = (List<Movement>) pageBeanVo.getItems();

        //3.遍历集合,获取每个动态,将动态和userInfo封装成MovementVo对象,将vo对象放入一个新集合voList中
        //3.1 新建一个集合存放最终返回的数据集合voList
        List<MovementVo> voList = new ArrayList<>();

        //3.2 遍历集合,获取每个动态
        if (CollUtil.isNotEmpty(items)) {
            items.forEach(movement -> {
                //3.3 将动态和userInfo封装成MovementVo对象
                MovementVo vo = new MovementVo();

                //先拷贝userInfo,后拷贝movement 切记切记
                vo.setUserInfo(userInfo);
                vo.setMovement(movement);

                //判断当前用户有无点赞
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.MOVEMENT_LIKE,userId,movement.getId().toString()))) {
                    vo.setHasLiked(1);
                }

                //3.4 将vo对象放入voList中
                voList.add(vo);
            });
        }

        //4.将voList设置给pageBeanVo
        pageBeanVo.setItems(voList);

        //5.返回pageBeanVo
        return ResponseEntity.ok(pageBeanVo);
    }

    public ResponseEntity findFriendMovementByPage(Integer pageNum, Integer pageSize) {
        //0.获取当前用户id
        Long userId = UserHolder.get().getId();
        //1.远程调用service获取pageBeanVo
        PageBeanVo pageBeanVo = movementService.findFriendMovementByPage(userId, pageNum, pageSize);

        //2.获取pageBeanVo中动态集合
        List<Movement> items = (List<Movement>) pageBeanVo.getItems();

        //3.遍历动态集合,获取每个动态,通过动态发布者id查询userInfo,将动态和userInfo封装成movementVo,将每个vo放入一个集合中voList中
        //3.1 创建movementVoList
        List<MovementVo> voList = new ArrayList<>();

        //3.2 遍历动态集合,获取每个动态
        if (CollUtil.isNotEmpty(items)) {
            items.forEach(movement->{
                //3.3 通过动态发布者id查询userInfo
                UserInfo userInfo = userInfoService.findById(movement.getUserId());

                //3.4 将动态和userInfo封装成movementVo
                //先封装userInfo,后封装动态
                MovementVo vo = new MovementVo();
                vo.setUserInfo(userInfo);
                vo.setMovement(movement);

                //判断当前用户有无点赞
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.MOVEMENT_LIKE,userId,movement.getId().toString()))) {
                    vo.setHasLiked(1);
                }

                //3.5 将每个vo放入一个集合中voList中
                voList.add(vo);
            });
        }

        //4.将voList设置给pageBeanVo
        pageBeanVo.setItems(voList);

        //5.返回pageBeanVo
        return ResponseEntity.ok(pageBeanVo);
    }

    public ResponseEntity findRecommendMovementByPage(Integer pageNum, Integer pageSize) {
        //0.获取当前用户id
        Long userId = UserHolder.get().getId();

        //1.远程调用service获取pageBeanVo
        PageBeanVo pageBeanVo = movementService.findRecommendMovementByPage(userId, pageNum, pageSize);

        //2.获取pageBeanVo中动态集合
        List<Movement> items = (List<Movement>) pageBeanVo.getItems();

        //3.遍历动态集合,获取每个动态,通过动态发布者id查询userInfo,将动态和userInfo封装成movementVo,将每个vo放入一个集合中voList中
        //3.1 创建movementVoList
        List<MovementVo> voList = new ArrayList<>();

        //3.2 遍历动态集合,获取每个动态
        if (CollUtil.isNotEmpty(items)) {
            items.forEach(movement->{
                //3.3 通过动态发布者id查询userInfo
                UserInfo userInfo = userInfoService.findById(movement.getUserId());

                //3.4 将动态和userInfo封装成movementVo
                //先封装userInfo,后封装动态
                MovementVo vo = new MovementVo();
                vo.setUserInfo(userInfo);
                vo.setMovement(movement);

                //判断当前用户有无点赞
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.MOVEMENT_LIKE,userId,movement.getId().toString()))) {
                    vo.setHasLiked(1);
                }

                //判断当前用户有无喜欢
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.MOVEMENT_LOVE,userId,movement.getId().toString()))) {
                    vo.setHasLoved(1);
                }

                //3.5 将每个vo放入一个集合中voList中
                voList.add(vo);
            });
        }

        //4.将voList设置给pageBeanVo
        pageBeanVo.setItems(voList);

        //5.返回pageBeanVo
        return ResponseEntity.ok(pageBeanVo);
    }

    public ResponseEntity movementLike(String publishId) {
        //1.获取登陆者id
        Long userId = UserHolder.get().getId();

        //2.通过动态id查询动态对象
        Movement movement = movementService.findById(new ObjectId(publishId));

        //3.封装comment对象
        Comment comment = new Comment();
        comment.setCreated(System.currentTimeMillis());
        comment.setPublishId(new ObjectId(publishId));
        comment.setCommentType(1);
        comment.setUserId(userId);
        comment.setPublishUserId(movement.getUserId());

        //4.远程调用service完成保存操作
        int count = commentService.save(comment);

        //5.往redis中保存当前用户的操作  key: movement_like:用户id_动态id     value:1
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.MOVEMENT_LIKE,userId,publishId),"1");

        //6.将用户的行为得分放入mq中
        mqMovementManager.sendMovement(userId,movement.getId(),MQMovementManager.MOVEMENT_LIKE);

        return ResponseEntity.ok(count);
    }

    public ResponseEntity movementDislike(String publishId) {
        //1.获取登陆者id
        Long userId = UserHolder.get().getId();

        //2.远程调用service完成操作
        int count = commentService.delete(userId, new ObjectId(publishId), 1);

        //3.删除redis中用户操作的标识
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.MOVEMENT_LIKE,userId,publishId));

        //6.将用户的行为得分放入mq中
        mqMovementManager.sendMovement(userId,new ObjectId(publishId),MQMovementManager.MOVEMENT_DISLIKE);

        return ResponseEntity.ok(count);
    }

    public ResponseEntity movementLove(String publishId) {
        //1.获取登陆者id
        Long userId = UserHolder.get().getId();

        //2.通过动态id查询动态对象
        Movement movement = movementService.findById(new ObjectId(publishId));

        //3.封装comment对象
        Comment comment = new Comment();
        comment.setCreated(System.currentTimeMillis());
        comment.setPublishId(new ObjectId(publishId));
        comment.setCommentType(3);
        comment.setUserId(userId);
        comment.setPublishUserId(movement.getUserId());

        //4.远程调用service完成保存操作
        int count = commentService.save(comment);

        //5.往redis中保存当前用户的操作  key: movement_love:用户id_动态id     value:1
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.MOVEMENT_LOVE,userId,publishId),"1");

        //6.将用户的行为得分放入mq中
        mqMovementManager.sendMovement(userId,movement.getId(),MQMovementManager.MOVEMENT_LOVE);

        return ResponseEntity.ok(count);
    }

    public ResponseEntity movementUnlove(String publishId) {
        //1.获取登陆者id
        Long userId = UserHolder.get().getId();

        //2.远程调用service完成操作
        int count = commentService.delete(userId, new ObjectId(publishId), 3);

        //3.删除redis中用户操作的标识
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.MOVEMENT_LOVE,userId,publishId));

        //6.将用户的行为得分放入mq中
        mqMovementManager.sendMovement(userId,new ObjectId(publishId),MQMovementManager.MOVEMENT_DISLOVE);

        return ResponseEntity.ok(count);
    }

    public ResponseEntity findById(String movementId) {
        //1.远程调用动态service查询动态对象
        Movement movement = movementService.findById(new ObjectId(movementId));

        //2.获取动态发布人id
        //3.远程调用userInfoService查询userInfo
        UserInfo userInfo = userInfoService.findById(movement.getUserId());

        //4.封装movementVo且返回
        MovementVo vo = new MovementVo();

        //先userInfo后movement
        vo.setUserInfo(userInfo);
        vo.setMovement(movement);

        //6.将用户的行为得分放入mq中
        mqMovementManager.sendMovement(UserHolder.get().getId(),movement.getId(),MQMovementManager.MOVEMENT_BROWSE);

        return ResponseEntity.ok(vo);
    }

    public ResponseEntity findCommentByPage(String movementId, Integer pageNum, Integer pageSize) {
        //1.远程调用service查询pageBeanVo
        PageBeanVo pageBeanVo = commentService.findCommentByPage(new ObjectId(movementId), pageNum, pageSize);

        //2.获取pageBeanVo中评论集合
        List<Comment> items = (List<Comment>) pageBeanVo.getItems();

        //3.遍历评论集合,获取每个评论,调用service查询评论发布人的userInfo,将userInfo和评论封装成commentVo,且将每个vo放入一个声明好的voList中
        //3.1 声明voList,存放返回的数据集合
        List<CommentVo> voList = new ArrayList<>();

        //3.2 遍历评论集合,获取每个评论,
        if (CollUtil.isNotEmpty(items)) {
            items.forEach(comment -> {
                //3.3 调用service查询评论发布人的userInfo
                UserInfo userInfo = userInfoService.findById(comment.getUserId());

                //3.4 将userInfo和评论封装成commentVo
                CommentVo vo = new CommentVo();
                vo.setId(comment.getId().toString());

                vo.setAvatar(userInfo.getAvatar());
                vo.setNickname(userInfo.getNickname());

                vo.setContent(comment.getContent());
                //使用hutool中工具类
                vo.setCreateDate(DateUtil.formatDateTime(new Date(comment.getCreated())));

                //TODO 实战的时候大家可以完成对评论的点赞

                //3.5 且将每个vo放入voList中
                voList.add(vo);
            });
        }

        //4.将voList封给pageBeanVo
        pageBeanVo.setItems(voList);

        //5.返回pageBeanVo
        return ResponseEntity.ok(pageBeanVo);
    }

    public void movementComment(String movementId, String content) {
        //1.获取登陆者id
        Long userId = UserHolder.get().getId();

        //2.通过动态id查询动态对象
        Movement movement = movementService.findById(new ObjectId(movementId));

        //3.封装comment对象
        Comment comment = new Comment();
        comment.setCreated(System.currentTimeMillis());
        comment.setPublishId(movement.getId());
        comment.setCommentType(2);
        comment.setUserId(userId);
        comment.setPublishUserId(movement.getUserId());
        comment.setContent(content);

        //4.远程调用service完成保存操作
        commentService.save(comment);

        //6.将用户的行为得分放入mq中
        mqMovementManager.sendMovement(userId,movement.getId(),MQMovementManager.MOVEMENT_COMMENT);
    }
}
